package com.crazyhat.crazyhat.service.impl;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crazyhat.crazyhat.attribute.TokenPayloadEnum;
import com.crazyhat.crazyhat.entity.Activity;
import com.crazyhat.crazyhat.mapper.ActivityMapper;
import com.crazyhat.crazyhat.pojo.ActivityPublish;
import com.crazyhat.crazyhat.pojo.ActivitySimple;
import com.crazyhat.crazyhat.pojo.ContentWithFile;
import com.crazyhat.crazyhat.service.IActivityService;
import com.crazyhat.crazyhat.service.IClubService;
import com.crazyhat.crazyhat.service.IParticipationService;
import com.crazyhat.crazyhat.utils.ThreadLocalUtil;


/**
 * <p>
 * 社团活动 服务实现类
 * </p>
 *
 * @author crazyhat
 * @since 2024-07-05
 */
@Service
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements IActivityService {

    @Autowired
    private ActivityMapper activityMapper;


    @Autowired
    private IParticipationService participationService;

    @Autowired
    private IClubService clubService;

    /**
     * 最小活动发布时间间隔，单位：minutes
     */
    private final int minimum_Interval_Time=60;

    /**
     * 获取全部的活动，分页
     */
    @Override
    public Page<ActivitySimple> getActivityList(Integer clubId,Integer pageNum,Integer pageSize) {

        if (!(clubService.isClubsVisibleForUser(clubId))) {
            return null;
        }

        Page<Activity> page=new Page<>(pageNum,pageSize);

        QueryWrapper<Activity> queryWrapper=new QueryWrapper<>();
        queryWrapper
            .eq("club_id", clubId)
            .select("activity_id","activity_name","publish_time")
            .orderByDesc("publish_time");

        Page<Activity> resultPage=activityMapper.selectPage(page, queryWrapper);

        return convertToSimple(resultPage);
    }

    /**
     * 获取进行中的活动，分页
     */
    @Override
    public Page<ActivitySimple> getActivityListInProgress(Integer clubId, Integer pageNum, Integer pageSize) {

        if (!(clubService.isClubsVisibleForUser(clubId))) {
            return null;
        }

        LocalDateTime localDateTime=LocalDateTime.now();

        Page<Activity> page=new Page<>(pageNum,pageSize);

        QueryWrapper<Activity> queryWrapper=new QueryWrapper<>();
        queryWrapper
            .eq("club_id", clubId)
            .ge("end_time", localDateTime)
            .select("activity_id","activity_name","publish_time")
            .orderByDesc("publish_time");

        Page<Activity> resultPage=activityMapper.selectPage(page, queryWrapper);

        return convertToSimple(resultPage);
    }

    /**
     * 将活动对象转换成简单活动对象
     * @param activityList
     * @return
     */
    private Page<ActivitySimple> convertToSimple(Page<Activity> activityList) {

        Page<ActivitySimple> activityPage=(Page<ActivitySimple>)activityList.convert(activity->{
            ActivitySimple activitySimple=new ActivitySimple();
            activitySimple.setActivityId(activity.getActivityId());
            activitySimple.setActivityName(activity.getActivityName());
            activitySimple.setPublishTime(activity.getPublishTime());

            return activitySimple;
        });

        return activityPage;
    }

    /**
     * 发布活动
     */
    @Override
    public Activity publishActivity(ActivityPublish activity) {

        if (activity==null) {
            return null;
        }

        if (!(clubService.isClubsVisibleForUser(activity.getClubId()))) {
            return null;
        }

        if(!(participationService.isCommunityManager(activity.getClubId()))){
            return null;
        }

        //结束时间在发布时间后的一小时内
        if (!(isValidOfActivityEndTime(activity.getEndTime()))) {
            throw new IllegalArgumentException("活动结束时间必须在晚于当前时间之后一小时");
        }

        Activity newActivity = new Activity();

        newActivity.setClubId(activity.getClubId());
        newActivity.setActivityName(activity.getActivityName());
        newActivity.setEndTime(activity.getEndTime());
        newActivity.setPublishTime(LocalDateTime.now());

        Map<String,Object> map=ThreadLocalUtil.get();
        Integer studentId=(Integer)map.get(TokenPayloadEnum.StudentId.getValue());
        String name=(String)map.get(TokenPayloadEnum.Name.getValue());

        //发布人信息设置
        newActivity.setOrganizerId(studentId);
        newActivity.setOrganizerName(name);

        //处理文件列表并转换为JSON
        ContentWithFile content=new ContentWithFile();
        content.setContent(activity.getContent());
        content.setFileList(activity.getFileList());
        newActivity.setActivityDescription(content.processAndConvertToJson());

        int result = activityMapper.insert(newActivity);

        if (result > 0) {
            String message="您加入的社团有新活动发布了！活动名称："+activity.getActivityName();
            clubService.notifyAllMembers(activity.getClubId(),message);
            return newActivity;
        } else {
            return null;
        }
    }


    /**
     * 删除活动
     */
    @Override
    public boolean deleteActivity(Integer activityId) {

        Map<String,Object> map=ThreadLocalUtil.get();
        Integer studentId=(Integer)map.get("studentId");

        if (hasDeletePower(studentId, activityId)) {

            activityMapper.deleteById(activityId);

            return true;
        }

        return false;
    }

    /**
     * 用户是否对已发布的活动有编辑权限
     */
    @Override
    public boolean hasActivityEditPower(Integer activityId) {

        Map<String, Object> map = ThreadLocalUtil.get();
        Integer studentId = (Integer) map.get(TokenPayloadEnum.StudentId.getValue());

        return hasDeletePower(studentId, activityId);
    }

    /**
     * 查询用户是否对活动有删除权限
     * @param studentId
     * @param activityId
     * @return
     */
    private boolean hasDeletePower(Integer studentId,Integer activityId) {

        Activity activity=activityMapper.selectById(activityId);

        if (activity==null) {
            return false;
        }

        // if (activity.getOrganizerId().equals(studentId)) {

        //     //活动发布人拥有删除活动的权限
        //     return true;
        // }

        Integer clubId=activity.getClubId();

        if (participationService.isCommunityManager(clubId)) {

            //社区管理员拥有删除活动的权限
            return true;
        }

        return false;
    }

    /**
     * 更新、修改活动，返回更新后的活动
     */
    @Override
    public Activity updateActivity(ActivityPublish activity) {

        if (activity==null) {
            return null;
        }

        Activity oldActivity=activityMapper.selectById(activity.getActivityId());
        if (oldActivity==null) {
            return null;
        }

        if (!(participationService.isCommunityManager(oldActivity.getClubId()))) {

            //如果不是社团一把手或二把手
            return null;
        }

        //检验结束时间是否有效
        if (activity.getEndTime()!=null) {
            if (!(isValidOfActivityEndTime(activity.getEndTime()))) {

                //结束时间无效
                return null;

            } else {
                oldActivity.setEndTime(activity.getEndTime());
            }
        }

        oldActivity.setActivityName(activity.getActivityName());

        //处理文件列表并转换为JSON
        ContentWithFile content=new ContentWithFile();
        content.setContent(activity.getContent());
        content.setFileList(activity.getFileList());
        oldActivity.setActivityDescription(content.processAndConvertToJson());

        if (activityMapper.updateById(oldActivity)>0) {
            return oldActivity;
        } else {
            return null;
        }
    }

    /**
     * 判断活动结束时间是否有效
     * @param time
     * @return 有效：true，无效：False
     */
    private boolean isValidOfActivityEndTime(LocalDateTime endTime){

        if (endTime==null) {
            return false;
        }

         //结束时间在当前时间的一小时内
        if(Duration.between(LocalDateTime.now(),endTime).toMinutes()< minimum_Interval_Time){
            return false;
        }

        return true;
    }
}
